1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31 package sun.security.krb5;
32
33 import java.io.File;
34 import java.io.FileInputStream;
35 import java.util.Hashtable;
36 import java.util.Vector;
37 import java.util.ArrayList;
38 import java.io.BufferedReader;
39 import java.io.InputStreamReader;
40 import java.io.IOException;
41 import java.util.Enumeration;
42 import java.util.StringTokenizer;
43 import java.net.InetAddress;
44 import java.net.UnknownHostException;
45 import java.util.List;
46 import sun.net.dns.ResolverConfiguration;
47 import sun.security.krb5.internal.crypto.EType;
48 import sun.security.krb5.internal.ktab.*;
49 import sun.security.krb5.internal.Krb5;
50
51
52
53
54
55
56 public class Config {
57
58
59
60
61 private static Config singleton = null;
62
63
64
65
66 private Hashtable<String,Object> stanzaTable;
67
68 private static boolean DEBUG = sun.security.krb5.internal.Krb5.DEBUG;
69
70
71 private static final int BASE16_0 = 1;
72 private static final int BASE16_1 = 16;
73 private static final int BASE16_2 = 16 * 16;
74 private static final int BASE16_3 = 16 * 16 * 16;
75
76
77
78
79 private final String defaultRealm;
80 private final String defaultKDC;
81
82
83 private static native String getWindowsDirectory(boolean isSystem);
84
85
86
87
88
89
90
91
92
93
94 public static synchronized Config getInstance() throws KrbException {
95 if (singleton == null) {
96 singleton = new Config();
97 }
98 return singleton;
99 }
100
101
102
103
104
105
106
107
108
109
110
111 public static synchronized void refresh() throws KrbException {
112 singleton = new Config();
113 KdcComm.initStatic();
114 }
115
116
117
118
119
120 private Config() throws KrbException {
121
122
123
124 String tmp =
125 java.security.AccessController.doPrivileged(
126 new sun.security.action.GetPropertyAction
127 ("java.security.krb5.kdc"));
128 if (tmp != null) {
129
130 defaultKDC = tmp.replace(':', ' ');
131 } else {
132 defaultKDC = null;
133 }
134 defaultRealm =
135 java.security.AccessController.doPrivileged(
136 new sun.security.action.GetPropertyAction
137 ("java.security.krb5.realm"));
138 if ((defaultKDC == null && defaultRealm != null) ||
139 (defaultRealm == null && defaultKDC != null)) {
140 throw new KrbException
141 ("System property java.security.krb5.kdc and " +
142 "java.security.krb5.realm both must be set or " +
143 "neither must be set.");
144 }
145
146
147 try {
148 Vector<String> configFile;
149 configFile = loadConfigFile();
150 stanzaTable = parseStanzaTable(configFile);
151 } catch (IOException ioe) {
152
153 }
154 }
155
156
157
158
159
160
161
162
163 public int getDefaultIntValue(String name) {
164 String result = null;
165 int value = Integer.MIN_VALUE;
166 result = getDefault(name);
167 if (result != null) {
168 try {
169 value = parseIntValue(result);
170 } catch (NumberFormatException e) {
171 if (DEBUG) {
172 System.out.println("Exception in getting value of " +
173 name + " " +
174 e.getMessage());
175 System.out.println("Setting " + name +
176 " to minimum value");
177 }
178 value = Integer.MIN_VALUE;
179 }
180 }
181 return value;
182 }
183
184
185
186
187
188
189
190
191
192
193
194 public int getDefaultIntValue(String name, String section) {
195 String result = null;
196 int value = Integer.MIN_VALUE;
197 result = getDefault(name, section);
198 if (result != null) {
199 try {
200 value = parseIntValue(result);
201 } catch (NumberFormatException e) {
202 if (DEBUG) {
203 System.out.println("Exception in getting value of " +
204 name +" in section " +
205 section + " " + e.getMessage());
206 System.out.println("Setting " + name +
207 " to minimum value");
208 }
209 value = Integer.MIN_VALUE;
210 }
211 }
212 return value;
213 }
214
215
216
217
218
219
220 public String getDefault(String name) {
221 if (stanzaTable == null) {
222 return null;
223 } else {
224 return getDefault(name, stanzaTable);
225 }
226 }
227
228
229
230
231
232
233
234
235
236 private String getDefault(String k, Hashtable t) {
237 String result = null;
238 String key;
239 if (stanzaTable != null) {
240 for (Enumeration e = t.keys(); e.hasMoreElements(); ) {
241 key = (String)e.nextElement();
242 Object ob = t.get(key);
243 if (ob instanceof Hashtable) {
244 result = getDefault(k, (Hashtable)ob);
245 if (result != null) {
246 return result;
247 }
248 } else if (key.equalsIgnoreCase(k)) {
249 if (ob instanceof String) {
250 return (String)(t.get(key));
251 } else if (ob instanceof Vector) {
252 result = "";
253 int length = ((Vector)ob).size();
254 for (int i = 0; i < length; i++) {
255 if (i == length -1) {
256 result +=
257 (String)(((Vector)ob).elementAt(i));
258 } else {
259 result +=
260 (String)(((Vector)ob).elementAt(i)) + " ";
261 }
262 }
263 return result;
264 }
265 }
266 }
267 }
268 return result;
269 }
270
271
272
273
274
275
276
277
278
279 public String getDefault(String name, String section) {
280 String stanzaName;
281 String result = null;
282 Hashtable subTable;
283
284 if (stanzaTable != null) {
285 for (Enumeration e = stanzaTable.keys(); e.hasMoreElements(); ) {
286 stanzaName = (String)e.nextElement();
287 subTable = (Hashtable)stanzaTable.get(stanzaName);
288 if (stanzaName.equalsIgnoreCase(section)) {
289 if (subTable.containsKey(name)) {
290 return (String)(subTable.get(name));
291 }
292 } else if (subTable.containsKey(section)) {
293 Object ob = subTable.get(section);
294 if (ob instanceof Hashtable) {
295 Hashtable temp = (Hashtable)ob;
296 if (temp.containsKey(name)) {
297 Object object = temp.get(name);
298 if (object instanceof Vector) {
299 result = "";
300 int length = ((Vector)object).size();
301 for (int i = 0; i < length; i++) {
302 if (i == length - 1) {
303 result +=
304 (String)(((Vector)object).elementAt(i));
305 } else {
306 result +=
307 (String)(((Vector)object).elementAt(i))
308 + " ";
309 }
310 }
311 } else {
312 result = (String)object;
313 }
314 }
315 }
316 }
317 }
318 }
319 return result;
320 }
321
322
323
324
325
326
327
328 public boolean getDefaultBooleanValue(String name) {
329 String val = null;
330 if (stanzaTable == null) {
331 val = null;
332 } else {
333 val = getDefault(name, stanzaTable);
334 }
335 if (val != null && val.equalsIgnoreCase("true")) {
336 return true;
337 } else {
338 return false;
339 }
340 }
341
342
343
344
345
346
347
348
349
350
351 public boolean getDefaultBooleanValue(String name, String section) {
352 String val = getDefault(name, section);
353 if (val != null && val.equalsIgnoreCase("true")) {
354 return true;
355 } else {
356 return false;
357 }
358 }
359
360
361
362
363
364
365
366
367
368
369
370
371 private int parseIntValue(String input) throws NumberFormatException {
372 int value = 0;
373 if (input.startsWith("+")) {
374 String temp = input.substring(1);
375 return Integer.parseInt(temp);
376 } else if (input.startsWith("0x")) {
377 String temp = input.substring(2);
378 char[] chars = temp.toCharArray();
379 if (chars.length > 8) {
380 throw new NumberFormatException();
381 } else {
382 for (int i = 0; i < chars.length; i++) {
383 int index = chars.length - i - 1;
384 switch (chars[i]) {
385 case '0':
386 value += 0;
387 break;
388 case '1':
389 value += 1 * getBase(index);
390 break;
391 case '2':
392 value += 2 * getBase(index);
393 break;
394 case '3':
395 value += 3 * getBase(index);
396 break;
397 case '4':
398 value += 4 * getBase(index);
399 break;
400 case '5':
401 value += 5 * getBase(index);
402 break;
403 case '6':
404 value += 6 * getBase(index);
405 break;
406 case '7':
407 value += 7 * getBase(index);
408 break;
409 case '8':
410 value += 8 * getBase(index);
411 break;
412 case '9':
413 value += 9 * getBase(index);
414 break;
415 case 'a':
416 case 'A':
417 value += 10 * getBase(index);
418 break;
419 case 'b':
420 case 'B':
421 value += 11 * getBase(index);
422 break;
423 case 'c':
424 case 'C':
425 value += 12 * getBase(index);
426 break;
427 case 'd':
428 case 'D':
429 value += 13 * getBase(index);
430 break;
431 case 'e':
432 case 'E':
433 value += 14 * getBase(index);
434 break;
435 case 'f':
436 case 'F':
437 value += 15 * getBase(index);
438 break;
439 default:
440 throw new NumberFormatException("Invalid numerical format");
441 }
442 }
443 }
444 if (value < 0) {
445 throw new NumberFormatException("Data overflow.");
446 }
447 } else {
448 value = Integer.parseInt(input);
449 }
450 return value;
451 }
452
453 private int getBase(int i) {
454 int result = 16;
455 switch (i) {
456 case 0:
457 result = BASE16_0;
458 break;
459 case 1:
460 result = BASE16_1;
461 break;
462 case 2:
463 result = BASE16_2;
464 break;
465 case 3:
466 result = BASE16_3;
467 break;
468 default:
469 for (int j = 1; j < i; j++) {
470 result *= 16;
471 }
472 }
473 return result;
474 }
475
476
477
478
479 private String find(String key1, String key2) {
480 String result;
481 if ((stanzaTable != null) &&
482 ((result = (String)
483 (((Hashtable)(stanzaTable.get(key1))).get(key2))) != null)) {
484 return result;
485 } else {
486 return "";
487 }
488 }
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518 private Vector<String> loadConfigFile() throws IOException {
519 try {
520 final String fileName = getFileName();
521 if (!fileName.equals("")) {
522 BufferedReader br = new BufferedReader(new InputStreamReader(
523 java.security.AccessController.doPrivileged(
524 new java.security.PrivilegedExceptionAction<FileInputStream> () {
525 public FileInputStream run() throws IOException {
526 return new FileInputStream(fileName);
527 }
528 })));
529 String Line;
530 Vector<String> v = new Vector<>();
531 String previous = null;
532 while ((Line = br.readLine()) != null) {
533
534
535 if (!(Line.startsWith("#") || Line.trim().isEmpty())) {
536 String current = Line.trim();
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551 if (current.equals("{")) {
552 if (previous == null) {
553 throw new IOException(
554 "Config file should not start with \"{\"");
555 }
556 previous += " " + current;
557 } else {
558 if (previous != null) {
559 v.addElement(previous);
560 }
561 previous = current;
562 }
563 }
564 }
565 if (previous != null) {
566 v.addElement(previous);
567 }
568
569 br.close();
570 return v;
571 }
572 return null;
573 } catch (java.security.PrivilegedActionException pe) {
574 throw (IOException)pe.getException();
575 }
576 }
577
578
579
580
581
582
583
584
585
586 private Hashtable<String,Object> parseStanzaTable(Vector<String> v) throws KrbException {
587 if (v == null) {
588 throw new KrbException("I/O error while reading" +
589 " configuration file.");
590 }
591 Hashtable<String,Object> table = new Hashtable<>();
592 for (int i = 0; i < v.size(); i++) {
593 String line = v.elementAt(i).trim();
594 if (line.equalsIgnoreCase("[realms]")) {
595 for (int count = i + 1; count < v.size() + 1; count++) {
596
597 if ((count == v.size()) ||
598 (v.elementAt(count).startsWith("["))) {
599 Hashtable<String,Hashtable<String,Vector<String>>> temp =
600 new Hashtable<>();
601 temp = parseRealmField(v, i + 1, count);
602 table.put("realms", temp);
603 i = count - 1;
604 break;
605 }
606 }
607 } else if (line.equalsIgnoreCase("[capaths]")) {
608 for (int count = i + 1; count < v.size() + 1; count++) {
609
610 if ((count == v.size()) ||
611 (v.elementAt(count).startsWith("["))) {
612 Hashtable<String,Hashtable<String,Vector<String>>> temp =
613 new Hashtable<>();
614 temp = parseRealmField(v, i + 1, count);
615 table.put("capaths", temp);
616 i = count - 1;
617 break;
618 }
619 }
620 } else if (line.startsWith("[") && line.endsWith("]")) {
621 String key = line.substring(1, line.length() - 1);
622 for (int count = i + 1; count < v.size() + 1; count++) {
623
624 if ((count == v.size()) ||
625 (v.elementAt(count).startsWith("["))) {
626 Hashtable<String,String> temp =
627 parseField(v, i + 1, count);
628 table.put(key, temp);
629 i = count - 1;
630 break;
631 }
632 }
633 }
634 }
635 return table;
636 }
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657 private String getFileName() {
658 String name =
659 java.security.AccessController.doPrivileged(
660 new sun.security.action.
661 GetPropertyAction("java.security.krb5.conf"));
662 if (name == null) {
663 name = java.security.AccessController.doPrivileged(
664 new sun.security.action.
665 GetPropertyAction("java.home")) + File.separator +
666 "lib" + File.separator + "security" +
667 File.separator + "krb5.conf";
668 if (!fileExists(name)) {
669 name = null;
670 String osname =
671 java.security.AccessController.doPrivileged(
672 new sun.security.action.GetPropertyAction("os.name"));
673 if (osname.startsWith("Windows")) {
674 try {
675 Credentials.ensureLoaded();
676 } catch (Exception e) {
677
678 }
679 if (Credentials.alreadyLoaded) {
680 String path = getWindowsDirectory(false);
681 if (path != null) {
682 if (path.endsWith("\\")) {
683 path = path + "krb5.ini";
684 } else {
685 path = path + "\\krb5.ini";
686 }
687 if (fileExists(path)) {
688 name = path;
689 }
690 }
691 if (name == null) {
692 path = getWindowsDirectory(true);
693 if (path != null) {
694 if (path.endsWith("\\")) {
695 path = path + "krb5.ini";
696 } else {
697 path = path + "\\krb5.ini";
698 }
699 name = path;
700 }
701 }
702 }
703 if (name == null) {
704 name = "c:\\winnt\\krb5.ini";
705 }
706 } else if (osname.startsWith("SunOS")) {
707 name = "/etc/krb5/krb5.conf";
708 } else {
709 name = "/etc/krb5.conf";
710 }
711 }
712 }
713 if (DEBUG) {
714 System.out.println("Config name: " + name);
715 }
716 return name;
717 }
718
719 private static String trimmed(String s) {
720 s = s.trim();
721 if (s.charAt(0) == '"' && s.charAt(s.length()-1) == '"' ||
722 s.charAt(0) == '\'' && s.charAt(s.length()-1) == '\'') {
723 s = s.substring(1, s.length()-1).trim();
724 }
725 return s;
726 }
727
728
729
730 private Hashtable<String,String> parseField(Vector<String> v, int start, int end) {
731 Hashtable<String,String> table = new Hashtable<>();
732 String line;
733 for (int i = start; i < end; i++) {
734 line = v.elementAt(i);
735 for (int j = 0; j < line.length(); j++) {
736 if (line.charAt(j) == '=') {
737 String key = (line.substring(0, j)).trim();
738 String value = trimmed(line.substring(j + 1));
739 table.put(key, value);
740 break;
741 }
742 }
743 }
744 return table;
745 }
746
747
748
749
750
751
752 private Hashtable<String,Hashtable<String,Vector<String>>> parseRealmField(Vector<String> v, int start, int end) {
753 Hashtable<String,Hashtable<String,Vector<String>>> table = new Hashtable<>();
754 String line;
755 for (int i = start; i < end; i++) {
756 line = v.elementAt(i).trim();
757 if (line.endsWith("{")) {
758 String key = "";
759 for (int j = 0; j < line.length(); j++) {
760 if (line.charAt(j) == '=') {
761 key = line.substring(0, j).trim();
762
763 break;
764 }
765 }
766 for (int k = i + 1; k < end; k++) {
767 boolean found = false;
768 line = v.elementAt(k).trim();
769 for (int l = 0; l < line.length(); l++) {
770 if (line.charAt(l) == '}') {
771 found = true;
772 break;
773 }
774 }
775 if (found == true) {
776 Hashtable<String,Vector<String>> temp = parseRealmFieldEx(v, i + 1, k);
777 table.put(key, temp);
778 i = k;
779 found = false;
780 break;
781 }
782
783 }
784 }
785 }
786 return table;
787 }
788
789
790
791
792 private Hashtable<String,Vector<String>> parseRealmFieldEx(Vector<String> v, int start, int end) {
793 Hashtable<String,Vector<String>> table = new Hashtable<>();
794 Vector<String> keyVector = new Vector<>();
795 Vector<String> nameVector = new Vector<>();
796 String line = "";
797 String key;
798 for (int i = start; i < end; i++) {
799 line = v.elementAt(i);
800 for (int j = 0; j < line.length(); j++) {
801 if (line.charAt(j) == '=') {
802 int index;
803 key = line.substring(0, j).trim();
804 if (! exists(key, keyVector)) {
805 keyVector.addElement(key);
806 nameVector = new Vector<String> ();
807 } else {
808 nameVector = table.get(key);
809 }
810 nameVector.addElement(trimmed(line.substring(j + 1)));
811 table.put(key, nameVector);
812 break;
813 }
814 }
815 }
816 return table;
817 }
818
819
820
821
822 private boolean exists(String key, Vector v) {
823 boolean exists = false;
824 for (int i = 0; i < v.size(); i++) {
825 if (((String)(v.elementAt(i))).equals(key)) {
826 exists = true;
827 }
828 }
829 return exists;
830 }
831
832
833
834
835
836 public void listTable() {
837 listTable(stanzaTable);
838 }
839
840 private void listTable(Hashtable table) {
841 Vector v = new Vector();
842 String key;
843 if (stanzaTable != null) {
844 for (Enumeration e = table.keys(); e.hasMoreElements(); ) {
845 key = (String)e.nextElement();
846 Object object = table.get(key);
847 if (table == stanzaTable) {
848 System.out.println("[" + key + "]");
849 }
850 if (object instanceof Hashtable) {
851 if (table != stanzaTable)
852 System.out.println("\t" + key + " = {");
853 listTable((Hashtable)object);
854 if (table != stanzaTable)
855 System.out.println("\t}");
856
857 } else if (object instanceof String) {
858 System.out.println("\t" + key + " = " +
859 (String)table.get(key));
860 } else if (object instanceof Vector) {
861 v = (Vector)object;
862 for (int i = 0; i < v.size(); i++) {
863 System.out.println("\t" + key + " = " +
864 (String)v.elementAt(i));
865 }
866 }
867 }
868 } else {
869 System.out.println("Configuration file not found.");
870 }
871 }
872
873
874
875
876
877 public int[] defaultEtype(String enctypes) {
878 String default_enctypes;
879 default_enctypes = getDefault(enctypes, "libdefaults");
880 String delim = " ";
881 StringTokenizer st;
882 int[] etype;
883 if (default_enctypes == null) {
884 if (DEBUG) {
885 System.out.println("Using builtin default etypes for " +
886 enctypes);
887 }
888 etype = EType.getBuiltInDefaults();
889 } else {
890 for (int j = 0; j < default_enctypes.length(); j++) {
891 if (default_enctypes.substring(j, j + 1).equals(",")) {
892
893
894 delim = ",";
895 break;
896 }
897 }
898 st = new StringTokenizer(default_enctypes, delim);
899 int len = st.countTokens();
900 ArrayList<Integer> ls = new ArrayList<>(len);
901 int type;
902 for (int i = 0; i < len; i++) {
903 type = getType(st.nextToken());
904 if ((type != -1) &&
905 (EType.isSupported(type))) {
906 ls.add(type);
907 }
908 }
909 if (ls.size() == 0) {
910 if (DEBUG) {
911 System.out.println(
912 "no supported default etypes for " + enctypes);
913 }
914 return null;
915 } else {
916 etype = new int[ls.size()];
917 for (int i = 0; i < etype.length; i++) {
918 etype[i] = ls.get(i);
919 }
920 }
921 }
922
923 if (DEBUG) {
924 System.out.print("default etypes for " + enctypes + ":");
925 for (int i = 0; i < etype.length; i++) {
926 System.out.print(" " + etype[i]);
927 }
928 System.out.println(".");
929 }
930 return etype;
931 }
932
933
934
935
936
937
938
939
940
941
942
943
944 public int getType(String input) {
945 int result = -1;
946 if (input == null) {
947 return result;
948 }
949 if (input.startsWith("d") || (input.startsWith("D"))) {
950 if (input.equalsIgnoreCase("des-cbc-crc")) {
951 result = EncryptedData.ETYPE_DES_CBC_CRC;
952 } else if (input.equalsIgnoreCase("des-cbc-md5")) {
953 result = EncryptedData.ETYPE_DES_CBC_MD5;
954 } else if (input.equalsIgnoreCase("des-mac")) {
955 result = Checksum.CKSUMTYPE_DES_MAC;
956 } else if (input.equalsIgnoreCase("des-mac-k")) {
957 result = Checksum.CKSUMTYPE_DES_MAC_K;
958 } else if (input.equalsIgnoreCase("des-cbc-md4")) {
959 result = EncryptedData.ETYPE_DES_CBC_MD4;
960 } else if (input.equalsIgnoreCase("des3-cbc-sha1") ||
961 input.equalsIgnoreCase("des3-hmac-sha1") ||
962 input.equalsIgnoreCase("des3-cbc-sha1-kd") ||
963 input.equalsIgnoreCase("des3-cbc-hmac-sha1-kd")) {
964 result = EncryptedData.ETYPE_DES3_CBC_HMAC_SHA1_KD;
965 }
966 } else if (input.startsWith("a") || (input.startsWith("A"))) {
967
968 if (input.equalsIgnoreCase("aes128-cts") ||
969 input.equalsIgnoreCase("aes128-cts-hmac-sha1-96")) {
970 result = EncryptedData.ETYPE_AES128_CTS_HMAC_SHA1_96;
971 } else if (input.equalsIgnoreCase("aes256-cts") ||
972 input.equalsIgnoreCase("aes256-cts-hmac-sha1-96")) {
973 result = EncryptedData.ETYPE_AES256_CTS_HMAC_SHA1_96;
974
975 } else if (input.equalsIgnoreCase("arcfour-hmac") ||
976 input.equalsIgnoreCase("arcfour-hmac-md5")) {
977 result = EncryptedData.ETYPE_ARCFOUR_HMAC;
978 }
979
980 } else if (input.equalsIgnoreCase("rc4-hmac")) {
981 result = EncryptedData.ETYPE_ARCFOUR_HMAC;
982 } else if (input.equalsIgnoreCase("CRC32")) {
983 result = Checksum.CKSUMTYPE_CRC32;
984 } else if (input.startsWith("r") || (input.startsWith("R"))) {
985 if (input.equalsIgnoreCase("rsa-md5")) {
986 result = Checksum.CKSUMTYPE_RSA_MD5;
987 } else if (input.equalsIgnoreCase("rsa-md5-des")) {
988 result = Checksum.CKSUMTYPE_RSA_MD5_DES;
989 }
990 } else if (input.equalsIgnoreCase("hmac-sha1-des3-kd")) {
991 result = Checksum.CKSUMTYPE_HMAC_SHA1_DES3_KD;
992 } else if (input.equalsIgnoreCase("hmac-sha1-96-aes128")) {
993 result = Checksum.CKSUMTYPE_HMAC_SHA1_96_AES128;
994 } else if (input.equalsIgnoreCase("hmac-sha1-96-aes256")) {
995 result = Checksum.CKSUMTYPE_HMAC_SHA1_96_AES256;
996 } else if (input.equalsIgnoreCase("hmac-md5-rc4") ||
997 input.equalsIgnoreCase("hmac-md5-arcfour") ||
998 input.equalsIgnoreCase("hmac-md5-enc")) {
999 result = Checksum.CKSUMTYPE_HMAC_MD5_ARCFOUR;
1000 } else if (input.equalsIgnoreCase("NULL")) {
1001 result = EncryptedData.ETYPE_NULL;
1002 }
1003
1004 return result;
1005 }
1006
1007
1008
1009
1010
1011
1012
1013 public void resetDefaultRealm(String realm) {
1014 if (DEBUG) {
1015 System.out.println(">>> Config try resetting default kdc " + realm);
1016 }
1017 }
1018
1019
1020
1021
1022
1023 public boolean useAddresses() {
1024 boolean useAddr = false;
1025
1026 String value = getDefault("no_addresses", "libdefaults");
1027 useAddr = (value != null && value.equalsIgnoreCase("false"));
1028 if (useAddr == false) {
1029
1030 value = getDefault("noaddresses", "libdefaults");
1031 useAddr = (value != null && value.equalsIgnoreCase("false"));
1032 }
1033 return useAddr;
1034 }
1035
1036
1037
1038
1039 public boolean useDNS(String name) {
1040 String value = getDefault(name, "libdefaults");
1041 if (value == null) {
1042 value = getDefault("dns_fallback", "libdefaults");
1043 if ("false".equalsIgnoreCase(value)) {
1044 return false;
1045 } else {
1046 return true;
1047 }
1048 } else {
1049 return value.equalsIgnoreCase("true");
1050 }
1051 }
1052
1053
1054
1055
1056 public boolean useDNS_KDC() {
1057 return useDNS("dns_lookup_kdc");
1058 }
1059
1060
1061
1062
1063 public boolean useDNS_Realm() {
1064 return useDNS("dns_lookup_realm");
1065 }
1066
1067
1068
1069
1070
1071
1072 public String getDefaultRealm() throws KrbException {
1073 if (defaultRealm != null) {
1074 return defaultRealm;
1075 }
1076 Exception cause = null;
1077 String realm = getDefault("default_realm", "libdefaults");
1078 if ((realm == null) && useDNS_Realm()) {
1079
1080 try {
1081 realm = getRealmFromDNS();
1082 } catch (KrbException ke) {
1083 cause = ke;
1084 }
1085 }
1086 if (realm == null) {
1087 realm = java.security.AccessController.doPrivileged(
1088 new java.security.PrivilegedAction<String>() {
1089 @Override
1090 public String run() {
1091 String osname = System.getProperty("os.name");
1092 if (osname.startsWith("Windows")) {
1093 return System.getenv("USERDNSDOMAIN");
1094 }
1095 return null;
1096 }
1097 });
1098 }
1099 if (realm == null) {
1100 KrbException ke = new KrbException("Cannot locate default realm");
1101 if (cause != null) {
1102 ke.initCause(cause);
1103 }
1104 throw ke;
1105 }
1106 return realm;
1107 }
1108
1109
1110
1111
1112
1113
1114
1115
1116 public String getKDCList(String realm) throws KrbException {
1117 if (realm == null) {
1118 realm = getDefaultRealm();
1119 }
1120 if (realm.equalsIgnoreCase(defaultRealm)) {
1121 return defaultKDC;
1122 }
1123 Exception cause = null;
1124 String kdcs = getDefault("kdc", realm);
1125 if ((kdcs == null) && useDNS_KDC()) {
1126
1127 try {
1128 kdcs = getKDCFromDNS(realm);
1129 } catch (KrbException ke) {
1130 cause = ke;
1131 }
1132 }
1133 if (kdcs == null) {
1134 kdcs = java.security.AccessController.doPrivileged(
1135 new java.security.PrivilegedAction<String>() {
1136 @Override
1137 public String run() {
1138 String osname = System.getProperty("os.name");
1139 if (osname.startsWith("Windows")) {
1140 String logonServer = System.getenv("LOGONSERVER");
1141 if (logonServer != null
1142 && logonServer.startsWith("\\\\")) {
1143 logonServer = logonServer.substring(2);
1144 }
1145 return logonServer;
1146 }
1147 return null;
1148 }
1149 });
1150 }
1151 if (kdcs == null) {
1152 if (defaultKDC != null) {
1153 return defaultKDC;
1154 }
1155 KrbException ke = new KrbException("Cannot locate KDC");
1156 if (cause != null) {
1157 ke.initCause(cause);
1158 }
1159 throw ke;
1160 }
1161 return kdcs;
1162 }
1163
1164
1165
1166
1167
1168
1169 private String getRealmFromDNS() throws KrbException {
1170
1171 String realm = null;
1172 String hostName = null;
1173 try {
1174 hostName = InetAddress.getLocalHost().getCanonicalHostName();
1175 } catch (UnknownHostException e) {
1176 KrbException ke = new KrbException(Krb5.KRB_ERR_GENERIC,
1177 "Unable to locate Kerberos realm: " + e.getMessage());
1178 ke.initCause(e);
1179 throw (ke);
1180 }
1181
1182 String mapRealm = PrincipalName.mapHostToRealm(hostName);
1183 if (mapRealm == null) {
1184
1185 List<String> srchlist = ResolverConfiguration.open().searchlist();
1186 for (String domain: srchlist) {
1187 realm = checkRealm(domain);
1188 if (realm != null) {
1189 break;
1190 }
1191 }
1192 } else {
1193 realm = checkRealm(mapRealm);
1194 }
1195 if (realm == null) {
1196 throw new KrbException(Krb5.KRB_ERR_GENERIC,
1197 "Unable to locate Kerberos realm");
1198 }
1199 return realm;
1200 }
1201
1202
1203
1204
1205
1206 private static String checkRealm(String mapRealm) {
1207 if (DEBUG) {
1208 System.out.println("getRealmFromDNS: trying " + mapRealm);
1209 }
1210 String[] records = null;
1211 String newRealm = mapRealm;
1212 while ((records == null) && (newRealm != null)) {
1213
1214 records = KrbServiceLocator.getKerberosService(newRealm);
1215 newRealm = Realm.parseRealmComponent(newRealm);
1216
1217 }
1218 if (records != null) {
1219 for (int i = 0; i < records.length; i++) {
1220 if (records[i].equalsIgnoreCase(mapRealm)) {
1221 return records[i];
1222 }
1223 }
1224 }
1225 return null;
1226 }
1227
1228
1229
1230
1231
1232
1233
1234 private String getKDCFromDNS(String realm) throws KrbException {
1235
1236 String kdcs = null;
1237 String[] srvs = null;
1238
1239 if (DEBUG) {
1240 System.out.println("getKDCFromDNS using UDP");
1241 }
1242 srvs = KrbServiceLocator.getKerberosService(realm, "_udp");
1243 if (srvs == null) {
1244
1245 if (DEBUG) {
1246 System.out.println("getKDCFromDNS using UDP");
1247 }
1248 srvs = KrbServiceLocator.getKerberosService(realm, "_tcp");
1249 }
1250 if (srvs == null) {
1251
1252 throw new KrbException(Krb5.KRB_ERR_GENERIC,
1253 "Unable to locate KDC for realm " + realm);
1254 }
1255 for (int i = 0; i < srvs.length; i++) {
1256 String value = srvs[i];
1257 for (int j = 0; j < srvs[i].length(); j++) {
1258
1259 if (value.charAt(j) == ':') {
1260 kdcs = (value.substring(0, j)).trim();
1261 }
1262 }
1263 }
1264 return kdcs;
1265 }
1266
1267 private boolean fileExists(String name) {
1268 return java.security.AccessController.doPrivileged(
1269 new FileExistsAction(name));
1270 }
1271
1272 static class FileExistsAction
1273 implements java.security.PrivilegedAction<Boolean> {
1274
1275 private String fileName;
1276
1277 public FileExistsAction(String fileName) {
1278 this.fileName = fileName;
1279 }
1280
1281 public Boolean run() {
1282 return new File(fileName).exists();
1283 }
1284 }
1285
1286 @Override
1287 public String toString() {
1288 StringBuffer sb = new StringBuffer();
1289 toStringIndented("", stanzaTable, sb);
1290 return sb.toString();
1291 }
1292 private static void toStringIndented(String prefix, Object obj,
1293 StringBuffer sb) {
1294 if (obj instanceof String) {
1295 sb.append(prefix);
1296 sb.append(obj);
1297 sb.append('\n');
1298 } else if (obj instanceof Hashtable) {
1299 Hashtable tab = (Hashtable)obj;
1300 for (Object o: tab.keySet()) {
1301 sb.append(prefix);
1302 sb.append(o);
1303 sb.append(" = {\n");
1304 toStringIndented(prefix + " ", tab.get(o), sb);
1305 sb.append(prefix + "}\n");
1306 }
1307 } else if (obj instanceof Vector) {
1308 Vector v = (Vector)obj;
1309 for (Object o: v.toArray()) {
1310 toStringIndented(prefix + " ", o, sb);
1311 }
1312 }
1313 }
1314 }